10236. N Ферзей – расстановка
Имеется шахматная доска с n * n клетками. Разместите на ней n ферзей таким образом, чтобы ни один ферзь не бил другого.
Вход.
Размер шахматной доски n (1 ≤ n ≤ 10).
Выход.
Если можно разместить всех n ферзей так, чтобы ни один
ферзь не был под ударом другого ферзя, то выведите n строк, содержащих n целых чисел. Целое число в i-ой
строке и j-ом столбце будет обозначать
ячейку (i, j)
доски, и равно 1, если ферзь находится в (i, j)
и 0 в противном случае. Если
имеется несколько способов расположения ферзей, то выведите любую комбинацию.
Если невозможно разместить всех n ферзей желаемым образом, то
выведите “Not possible” (без кавычек).
Пример входа |
Пример выхода |
4 |
0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 |
бектрекинг
Для хранения
информации о расстановке ферзей на шахматной доске будем использвать двумерный
массив mat:
·
mat[i][j]
= 1, если в позиции (i, j) находится ферзь;
·
mat[i][j]
= 0, если в позиции (i, j) нет ферзя;
Изначально на доске
ферзей нет (mat[i][j]
= 0). Берем первую позицию (1, 1) и ставим на нее ферзя (mat[1][1] = 1). Ищем следующую позицию, например (2, 3), которую не бъет
первый ферзь, и ставим туда второго ферзя. Далее ищем такую
позицию, которую не бъют уже два поставленных ферзя. Такой, например, может
быть (3, 5), куда ставим третьего ферзя.
Перебираем позиции (i, j) далее
и ищем такую, в которую можно поставить очередного ферзя. Когда все клетки
доски будут просмотрены, а все n ферзей
расстановлены не будут, начинаем бектрекинг – возврат назад. Пробуем изменить
положение последнего ферзя, найдя ему другое подходящее место. Когда все
позиции этого ферзя будут перебраны, изменяем положение предыдущего ферзя и так
далее продолжаем поиск с возвратом пока не будут расставлены все n ферзей.
Реализация алгоритма
В массиве mat будем генерировать шахматную доску.
int mat[11][11];
Функция attacked проверяет, будет ли атакован хотя бы один ферзь из
позиции (i, j).
int attacked(int x, int y)
{
if (mat[x][y])return 1;
for (int i = 1; i <=
n; i++)
{
if (y - i >= 1
&& mat[x][y - i]) return 1;
if (y + i <= n
&& mat[x][y + i]) return 1;
if (x - i >= 1
&& mat[x - i][y]) return 1;
if (x + i <= n
&& mat[x + i][y]) return 1;
if (x - i >= 1
&& y - i >= 1 && mat[x - i][y - i]) return 1;
if (x + i <= n
&& y + i <= n && mat[x + i][y + i]) return 1;
if (x + i <= n
&& y - i >= 1 && mat[x + i][y - i]) return 1;
if (x - i >= 1
&& y + i <= n && mat[x - i][y + i]) return 1;
}
return 0;
}
Функция print выводит шахматную доску.
void print(void)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
printf("%d ", mat[i][j]);
printf("\n");
}
}
Функция solve расставляет на доске еще x ферзей так, чтобы они
не били друг друга.
int solve(int x)
{
Если x = 0, то все n ферзей
расставлены. Выводим состояние доски.
if (x == 0)
{
print();
return 1;
}
Перебираем позиции (i, j), проверяем можно ли поставить в (i,
j) ферзя так,
чтобы он не бил уже расставленные.
for (int i = 1; i <=
n; i++)
for (int j = 1; j <=
n; j++)
{
if (attacked(i, j)
== 1) continue;
В позицию (i, j) ставим ферзя.
mat[i][j] = 1;
На остальной доске расставляем x – 1 ферзей.
if (solve(x - 1)) return 1;
Из позиции (i, j) убираем ферзя и совершаем ход
назад (бектрекинг)
mat[i][j] = 0;
}
return 0;
}
Основная часть программы. Читаем размер доски n.
scanf("%d", &n);
Производим расстановку n ферзей.
Если расстановка возможна, то она будет выведена. Иначе выведем сообщение “Not possible”.
if (!solve(n)) puts("Not possible");
Java реализация
import java.util.*;
public class Main
{
static boolean mat[][];
static int n;
static boolean attacked(int x, int y)
{
if (mat[x][y]) return true;
for (int i = 1; i <= n; i++)
{
if (y - i >= 1
&& mat[x][y - i]) return true;
if (y + i <= n && mat[x][y + i]) return true;
if (x - i >= 1
&& mat[x - i][y]) return true;
if (x + i <= n && mat[x + i][y]) return true;
if (x - i >= 1
&& y - i >= 1 && mat[x - i][y - i]) return true;
if (x + i <= n && y + i <= n && mat[x + i][y + i]) return true;
if (x + i <= n && y - i >= 1
&& mat[x + i][y - i]) return true;
if (x - i >= 1
&& y + i <= n && mat[x - i][y + i]) return true;
}
return false;
}
static void print()
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
System.out.print(mat[i][j] ? 1 + " " : 0 + " ");
System.out.println();
}
}
static boolean solve(int x)
{
if (x == 0)
{
print();
return true;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
if (attacked(i, j)) continue;
mat[i][j] = true;
if (solve(x - 1)) return true;
mat[i][j] = false;
}
return false;
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
n = con.nextInt();
mat = new boolean[n+1][n+1];
if (!solve(n)) System.out.println("Not
possible");
con.close();
}
}